using System.Web.UI;
using System.Web.UI.HtmlControls;

namespace FluentTags
{

    public class ATag : Tag<ATag>
    {
        public ATag() : base("a"){}
        
        public ATag(string text) : this()
        {
            Controls.Add(new LiteralControl(text));
        }

        public ATag(object value) : this()
        {
            Controls.Add(new LiteralControl(SafeString(value)));
        }
        
        
        public ATag(Control control) : this()
        {
            Controls.Add(control);
        }
        
        
        public ATag Charset(string value)
        {   
            Attributes.Add("charset", value.ToString());
            return this;
        }
        
        public ATag Coords(string value)
        {   
            Attributes.Add("coords", value.ToString());
            return this;
        }
        
        public ATag Href(string value)
        {   
            if(!value.StartsWith("#"))
            {
                value = ResolveUrl(value);
            }
                    
            Attributes.Add("href", value.ToString());
            return this;
        }
        
        public ATag Hreflang(string value)
        {   
            Attributes.Add("hreflang", value.ToString());
            return this;
        }
        
        public ATag Name(string value)
        {   
            Attributes.Add("name", value.ToString());
            return this;
        }
        
        public ATag Rel(string value)
        {   
            Attributes.Add("rel", value.ToString());
            return this;
        }
        
        public ATag Rev(string value)
        {   
            Attributes.Add("rev", value.ToString());
            return this;
        }
        
        public ATag Shape(string value)
        {   
            Attributes.Add("shape", value.ToString());
            return this;
        }
        
        public ATag Type(string value)
        {   
            Attributes.Add("type", value.ToString());
            return this;
        }
        
        
        public string CharsetAttribute
        {
            get
            {
                return Attributes["charset"];
            }
        }
        
        public string CoordsAttribute
        {
            get
            {
                return Attributes["coords"];
            }
        }
        
        public string HrefAttribute
        {
            get
            {
                return Attributes["href"];
            }
        }
        
        public string HreflangAttribute
        {
            get
            {
                return Attributes["hreflang"];
            }
        }
        
        public string NameAttribute
        {
            get
            {
                return Attributes["name"];
            }
        }
        
        public string RelAttribute
        {
            get
            {
                return Attributes["rel"];
            }
        }
        
        public string RevAttribute
        {
            get
            {
                return Attributes["rev"];
            }
        }
        
        public string ShapeAttribute
        {
            get
            {
                return Attributes["shape"];
            }
        }
        
        public string TypeAttribute
        {
            get
            {
                return Attributes["type"];
            }
        }
        
        
        public BTag<ATag> B()
        {
            var ctrl = new BTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag B(BTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public BTag<ATag> B(string text)
        {
            var ctrl = new BTag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public BTag<ATag> B(Control control)
        {
            var ctrl = new BTag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public BTag<ATag> B(object value)
        {
            return B(SafeString(value));
        }
        
        public BRTag<ATag> BR()
        {
            var ctrl = new BRTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag BR(BRTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public EMTag<ATag> EM()
        {
            var ctrl = new EMTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag EM(EMTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public EMTag<ATag> EM(string text)
        {
            var ctrl = new EMTag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public EMTag<ATag> EM(Control control)
        {
            var ctrl = new EMTag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public EMTag<ATag> EM(object value)
        {
            return EM(SafeString(value));
        }
        
        public ITag<ATag> I()
        {
            var ctrl = new ITag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag I(ITag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public ITag<ATag> I(string text)
        {
            var ctrl = new ITag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public ITag<ATag> I(Control control)
        {
            var ctrl = new ITag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public ITag<ATag> I(object value)
        {
            return I(SafeString(value));
        }
        
        public ImgTag<ATag> Img()
        {
            var ctrl = new ImgTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag Img(ImgTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SpanTag<ATag> Span()
        {
            var ctrl = new SpanTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag Span(SpanTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SpanTag<ATag> Span(string text)
        {
            var ctrl = new SpanTag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public SpanTag<ATag> Span(Control control)
        {
            var ctrl = new SpanTag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public SpanTag<ATag> Span(object value)
        {
            return Span(SafeString(value));
        }
        
        public StrongTag<ATag> Strong()
        {
            var ctrl = new StrongTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag Strong(StrongTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public StrongTag<ATag> Strong(string text)
        {
            var ctrl = new StrongTag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public StrongTag<ATag> Strong(Control control)
        {
            var ctrl = new StrongTag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public StrongTag<ATag> Strong(object value)
        {
            return Strong(SafeString(value));
        }
        
        public SubTag<ATag> Sub()
        {
            var ctrl = new SubTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag Sub(SubTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SubTag<ATag> Sub(string text)
        {
            var ctrl = new SubTag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public SubTag<ATag> Sub(Control control)
        {
            var ctrl = new SubTag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public SubTag<ATag> Sub(object value)
        {
            return Sub(SafeString(value));
        }
        
        public SupTag<ATag> Sup()
        {
            var ctrl = new SupTag<ATag>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag Sup(SupTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SupTag<ATag> Sup(string text)
        {
            var ctrl = new SupTag<ATag>(this);
            Controls.Add(ctrl);
            LiteralControl lc = new LiteralControl(text);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public SupTag<ATag> Sup(Control control)
        {
            var ctrl = new SupTag<ATag>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public SupTag<ATag> Sup(object value)
        {
            return Sup(SafeString(value));
        }
        
        
        public ATag Text(string text)
        {
            Controls.Add(new LiteralControl(text));
            return this;
        }

        public ATag Text(object value)
        {
            Controls.Add(new LiteralControl(SafeString(value)));
            return this;
        }
        
    }

    public class ATag<ParentType> : ChildTag<ATag<ParentType>, ParentType>
        where ParentType : HtmlGenericControl
    {
        public ATag(ParentType parent) : base("a", parent) { }

        
        public ATag<ParentType> Charset(string value)
        {   
            Attributes.Add("charset", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Coords(string value)
        {   
            Attributes.Add("coords", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Href(string value)
        {   
            if(!value.StartsWith("#"))
            {
                value = ResolveUrl(value);
            }
                    
            Attributes.Add("href", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Hreflang(string value)
        {   
            Attributes.Add("hreflang", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Name(string value)
        {   
            Attributes.Add("name", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Rel(string value)
        {   
            Attributes.Add("rel", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Rev(string value)
        {   
            Attributes.Add("rev", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Shape(string value)
        {   
            Attributes.Add("shape", value.ToString());
            return this;
        }
        
        public ATag<ParentType> Type(string value)
        {   
            Attributes.Add("type", value.ToString());
            return this;
        }
        
        
        public string CharsetAttribute
        {
            get
            {
                return Attributes["charset"];
            }
        }
        
        public string CoordsAttribute
        {
            get
            {
                return Attributes["coords"];
            }
        }
        
        public string HrefAttribute
        {
            get
            {
                return Attributes["href"];
            }
        }
        
        public string HreflangAttribute
        {
            get
            {
                return Attributes["hreflang"];
            }
        }
        
        public string NameAttribute
        {
            get
            {
                return Attributes["name"];
            }
        }
        
        public string RelAttribute
        {
            get
            {
                return Attributes["rel"];
            }
        }
        
        public string RevAttribute
        {
            get
            {
                return Attributes["rev"];
            }
        }
        
        public string ShapeAttribute
        {
            get
            {
                return Attributes["shape"];
            }
        }
        
        public string TypeAttribute
        {
            get
            {
                return Attributes["type"];
            }
        }
        
        
        public BTag<ATag<ParentType>> B()
        {
            var ctrl = new BTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> B(BTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public BTag<ATag<ParentType>> B(string text)
        {
            var ctrl = new BTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public BTag<ATag<ParentType>> B(Control control)
        {
            var ctrl = new BTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public BTag<ATag<ParentType>> B(object value)
        {
            var ctrl = new BTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        public BRTag<ATag<ParentType>> BR()
        {
            var ctrl = new BRTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> BR(BRTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public EMTag<ATag<ParentType>> EM()
        {
            var ctrl = new EMTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> EM(EMTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public EMTag<ATag<ParentType>> EM(string text)
        {
            var ctrl = new EMTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public EMTag<ATag<ParentType>> EM(Control control)
        {
            var ctrl = new EMTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public EMTag<ATag<ParentType>> EM(object value)
        {
            var ctrl = new EMTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        public ITag<ATag<ParentType>> I()
        {
            var ctrl = new ITag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> I(ITag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public ITag<ATag<ParentType>> I(string text)
        {
            var ctrl = new ITag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public ITag<ATag<ParentType>> I(Control control)
        {
            var ctrl = new ITag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public ITag<ATag<ParentType>> I(object value)
        {
            var ctrl = new ITag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        public ImgTag<ATag<ParentType>> Img()
        {
            var ctrl = new ImgTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> Img(ImgTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SpanTag<ATag<ParentType>> Span()
        {
            var ctrl = new SpanTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> Span(SpanTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SpanTag<ATag<ParentType>> Span(string text)
        {
            var ctrl = new SpanTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public SpanTag<ATag<ParentType>> Span(Control control)
        {
            var ctrl = new SpanTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public SpanTag<ATag<ParentType>> Span(object value)
        {
            var ctrl = new SpanTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        public StrongTag<ATag<ParentType>> Strong()
        {
            var ctrl = new StrongTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> Strong(StrongTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public StrongTag<ATag<ParentType>> Strong(string text)
        {
            var ctrl = new StrongTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public StrongTag<ATag<ParentType>> Strong(Control control)
        {
            var ctrl = new StrongTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public StrongTag<ATag<ParentType>> Strong(object value)
        {
            var ctrl = new StrongTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        public SubTag<ATag<ParentType>> Sub()
        {
            var ctrl = new SubTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> Sub(SubTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SubTag<ATag<ParentType>> Sub(string text)
        {
            var ctrl = new SubTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public SubTag<ATag<ParentType>> Sub(Control control)
        {
            var ctrl = new SubTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public SubTag<ATag<ParentType>> Sub(object value)
        {
            var ctrl = new SubTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        public SupTag<ATag<ParentType>> Sup()
        {
            var ctrl = new SupTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            return ctrl;
        }

        public ATag<ParentType> Sup(SupTag child)
        {
            Controls.Add(child);
            return this;
        }
        
        public SupTag<ATag<ParentType>> Sup(string text)
        {
            var ctrl = new SupTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(text);
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            
            return ctrl;
        }

        public SupTag<ATag<ParentType>> Sup(Control control)
        {
            var ctrl = new SupTag<ATag<ParentType>>(this);
            Controls.Add(ctrl);
            ctrl.Controls.Add(control);
            
            return ctrl;
        }

        public SupTag<ATag<ParentType>> Sup(object value)
        {
            var ctrl = new SupTag<ATag<ParentType>>(this);
            LiteralControl lc = new LiteralControl(SafeString(value));
            Controls.Add(ctrl);
            ctrl.Controls.Add(lc);
            return ctrl;
        }
        
        
        public ATag<ParentType> Text(string text)
        {
            Controls.Add(new LiteralControl(text));
            return this;
        }
        
        public ATag<ParentType> Text(object value)
        {
            Controls.Add(new LiteralControl(SafeString(value)));
            return this;
        }
        
        
    }
}